package com.gitee.fastmybatis.core.query;

import com.gitee.fastmybatis.core.query.expression.BetweenValue;
import com.gitee.fastmybatis.core.query.expression.ValueConvert;

import java.util.Collection;
import java.util.List;

/**
 * or 条件
 *
 * @author thc
 */
public interface ConditionOr<T> {

    Condition getCondition();

    /**
     * 添加等于条件
     *
     * @param columnName 数据库字段名
     * @param value      值
     * @return 返回Query对象
     */
    default T orEq(String columnName, Object value) {
        getCondition().orEq(columnName, value);
        return (T) this;
    }

    /**
     * 根据表达式添加等于条件
     * <pre>
     *     query.orEq(StringUtils.hasText(name), "name", name);
     *     等同于：
     *     if (StringUtils.hasText(name)) {
     *         query.orEq("name", name);
     *     }
     * </pre>
     *
     * @param expression 表达式，当为true时添加条件
     * @param columnName 数据库字段名
     * @param value      值
     * @return 返回Query对象
     */
    default T orEq(boolean expression, String columnName, Object value) {
        if (expression) {
            orEq(columnName, value);
        }
        return (T) this;
    }

    /**
     * 添加不等于条件
     *
     * @param columnName 数据库字段名
     * @param value      值
     * @return 返回Query对象
     */
    default T orNotEq(String columnName, Object value) {
        getCondition().orNotEq(columnName, value);
        return (T) this;
    }

    /**
     * 根据表达式添加不等于条件
     *
     * @param expression 表达式，当为true时添加条件
     * @param columnName 数据库字段名
     * @param value      值
     * @return 返回Query对象
     */
    default T orNotEq(boolean expression, String columnName, Object value) {
        if (expression) {
            orNotEq(columnName, value);
        }
        return (T) this;
    }

    /**
     * 添加大于条件,>
     *
     * @param columnName 数据库字段名
     * @param value      值
     * @return 返回Query对象
     */
    default T orGt(String columnName, Object value) {
        getCondition().orGt(columnName, value);
        return (T) this;
    }

    /**
     * 根据表达式添加大于条件,>
     *
     * @param expression 表达式，当为true时添加条件
     * @param columnName 数据库字段名
     * @param value      值
     * @return 返回Query对象
     */
    default T orGt(boolean expression, String columnName, Object value) {
        if (expression) {
            orGt(columnName, value);
        }
        return (T) this;
    }

    /**
     * 添加大于等于条件,>=
     *
     * @param columnName 数据库字段名
     * @param value      值
     * @return 返回Query对象
     */
    default T orGe(String columnName, Object value) {
        getCondition().orGe(columnName, value);
        return (T) this;
    }

    /**
     * 根据表达式添加大于等于条件,>=
     *
     * @param expression 表达式，当为true时添加条件
     * @param columnName 数据库字段名
     * @param value      值
     * @return 返回Query对象
     */
    default T orGe(boolean expression, String columnName, Object value) {
        if (expression) {
            orGe(columnName, value);
        }
        return (T) this;
    }

    /**
     * 添加小于条件,<
     *
     * @param columnName 数据库字段名
     * @param value      值
     * @return 返回Query对象
     */
    default T orLt(String columnName, Object value) {
        getCondition().orLt(columnName, value);
        return (T) this;
    }

    /**
     * 根据表达式添加小于条件,<
     *
     * @param expression 表达式，当为true时添加条件
     * @param columnName 数据库字段名
     * @param value      值
     * @return 返回Query对象
     */
    default T orLt(boolean expression, String columnName, Object value) {
        if (expression) {
            orLt(columnName, value);
        }
        return (T) this;
    }

    /**
     * 小于等于,<=
     *
     * @param columnName 数据库字段名
     * @param value      值
     * @return 返回Query对象
     */
    default T orLe(String columnName, Object value) {
        getCondition().orLe(columnName, value);
        return (T) this;
    }

    /**
     * 根据表达式小于等于条件,<=
     *
     * @param expression 表达式，当为true时添加条件
     * @param columnName 数据库字段名
     * @param value      值
     * @return 返回Query对象
     */
    default T orLe(boolean expression, String columnName, Object value) {
        if (expression) {
            orLe(columnName, value);
        }
        return (T) this;
    }

    /**
     * 添加两边模糊查询条件，两边模糊匹配，即name like '%value%'
     *
     * @param columnName 数据库字段名
     * @param value      值,不需要加%
     * @return 返回Query对象
     * @see #orLikeLeft(String, String) 左边模糊匹配
     * @see #orLikeRight(String, String) 右边模糊匹配
     */
    default T orLike(String columnName, String value) {
        getCondition().orLike(columnName, value);
        return (T) this;
    }

    /**
     * 根据表达式添加两边模糊查询条件，两边模糊匹配，即name like '%value%'
     *
     * @param expression 表达式，当为true时添加条件
     * @param columnName 数据库字段名
     * @param value      值,不需要加%
     * @return 返回Query对象
     * @see #orLikeLeft(boolean, String, String) 左模糊
     * @see #orLikeRight(boolean, String, String) 右模糊
     */
    default T orLike(boolean expression, String columnName, String value) {
        if (expression) {
            orLike(columnName, value);
        }
        return (T) this;
    }

    /**
     * 添加左模糊查询条件，左边模糊匹配，即name like '%value'
     *
     * @param columnName 数据库字段名
     * @param value      值,不需要加%
     * @return 返回Query对象
     */
    default T orLikeLeft(String columnName, String value) {
        getCondition().orLikeLeft(columnName, value);
        return (T) this;
    }

    /**
     * 根据表达式添加左模糊查询条件，左边模糊匹配，即name like '%value'
     *
     * @param expression 表达式，当为true时添加条件
     * @param columnName 数据库字段名
     * @param value      值,不需要加%
     * @return 返回Query对象
     */
    default T orLikeLeft(boolean expression, String columnName, String value) {
        if (expression) {
            orLikeLeft(columnName, value);
        }
        return (T) this;
    }

    /**
     * 添加右模糊查询条件，右边模糊匹配，即name like 'value%'。mysql推荐用这种
     *
     * @param columnName 数据库字段名
     * @param value      值,不需要加%
     * @return 返回Query对象
     */
    default T orLikeRight(String columnName, String value) {
        getCondition().orLikeRight(columnName, value);
        return (T) this;
    }

    /**
     * 根据表达式添加右模糊查询条件，右边模糊匹配，即name like 'value%'。mysql推荐用这种
     *
     * @param expression 表达式，当为true时添加条件
     * @param columnName 数据库字段名
     * @param value      值,不需要加%
     * @return 返回Query对象
     */
    default T orLikeRight(boolean expression, String columnName, String value) {
        if (expression) {
            orLikeRight(columnName, value);
        }
        return (T) this;
    }

    /**
     * 添加IN条件
     *
     * @param columnName 数据库字段名
     * @param value      值
     * @return 返回Query对象
     */
    default T orIn(String columnName, Collection<?> value) {
        getCondition().orIn(columnName, value);
        return (T) this;
    }

    /**
     * 根据表达式添加IN条件
     *
     * @param expression 表达式，当为true时添加条件
     * @param columnName 数据库字段名
     * @param value      值
     * @return 返回Query对象
     */
    default T orIn(boolean expression, String columnName, Collection<?> value) {
        if (expression) {
            orIn(columnName, value);
        }
        return (T) this;
    }

    /**
     * 添加IN条件
     *
     * @param columnName   数据库字段名
     * @param value        值
     * @param valueConvert 转换
     * @return 返回Query对象
     */
    default <E> T orIn(String columnName, Collection<E> value, ValueConvert<E> valueConvert) {
        getCondition().orIn(columnName, value, valueConvert);
        return (T) this;
    }

    /**
     * 根据表达式添加IN条件
     *
     * @param expression   表达式，当为true时添加条件
     * @param columnName   数据库字段名
     * @param value        值
     * @param valueConvert 转换
     * @return 返回Query对象
     */
    default <E> T orIn(boolean expression, String columnName, Collection<E> value, ValueConvert<E> valueConvert) {
        if (expression) {
            orIn(columnName, value, valueConvert);
        }
        return (T) this;
    }

    /**
     * 添加IN条件
     *
     * @param columnName 数据库字段名
     * @param value      值
     * @return 返回Query对象
     */
    default T orIn(String columnName, Object[] value) {
        getCondition().orIn(columnName, value);
        return (T) this;
    }

    /**
     * 根据表达式添加IN条件
     *
     * @param expression 表达式，当为true时添加条件
     * @param columnName 数据库字段名
     * @param value      值
     * @return 返回Query对象
     */
    default T orIn(boolean expression, String columnName, Object[] value) {
        if (expression) {
            orIn(columnName, value);
        }
        return (T) this;
    }

    /**
     * 添加not in条件
     *
     * @param columnName 数据库字段名
     * @param value      值
     * @return 返回Query对象
     */
    default T orNotIn(String columnName, Collection<?> value) {
        getCondition().orNotIn(columnName, value);
        return (T) this;
    }

    /**
     * 根据表达式添加not in条件
     *
     * @param expression 表达式，当为true时添加条件
     * @param columnName 数据库字段名
     * @param value      值
     * @return 返回Query对象
     */
    default T orNotIn(boolean expression, String columnName, Collection<?> value) {
        if (expression) {
            orNotIn(columnName, value);
        }
        return (T) this;
    }

    /**
     * 添加not in条件
     *
     * @param columnName   数据库字段名
     * @param value        值
     * @param valueConvert 转换器
     * @return 返回Query对象
     */
    default <E> T orNotIn(String columnName, Collection<E> value, ValueConvert<E> valueConvert) {
        getCondition().orNotIn(columnName, value, valueConvert);
        return (T) this;
    }

    /**
     * 根据表达式添加not in条件
     *
     * @param expression   表达式，当为true时添加条件
     * @param columnName   数据库字段名
     * @param value        值
     * @param valueConvert 转换器
     * @return 返回Query对象
     */
    default <E> T orNotIn(boolean expression, String columnName, Collection<E> value, ValueConvert<E> valueConvert) {
        if (expression) {
            orNotIn(columnName, value, valueConvert);
        }
        return (T) this;
    }

    /**
     * 添加not in条件
     *
     * @param columnName 数据库字段名
     * @param value      值
     * @return 返回Query对象
     */
    default T orNotIn(String columnName, Object[] value) {
        getCondition().orNotIn(columnName, value);
        return (T) this;
    }

    /**
     * 根据表达式添加not in条件
     *
     * @param expression 表达式，当为true时添加条件
     * @param columnName 数据库字段名
     * @param value      值
     * @return 返回Query对象
     */
    default T orNotIn(boolean expression, String columnName, Object[] value) {
        if (expression) {
            orNotIn(columnName, value);
        }
        return (T) this;
    }

    /**
     * 添加between条件
     *
     * @param columnName 数据库字段名
     * @param startValue 起始值
     * @param endValue   结束值
     * @return 返回Query对象
     */
    default T orBetween(String columnName, Object startValue, Object endValue) {
        getCondition().orBetween(columnName, startValue, endValue);
        return (T) this;
    }

    /**
     * 添加between条件
     *
     * @param expression 表达式，当为true时添加条件
     * @param columnName 数据库字段名
     * @param startValue 起始值
     * @param endValue   结束值
     * @return 返回Query对象
     */
    default T orBetween(boolean expression, String columnName, Object startValue, Object endValue) {
        if (expression) {
            orBetween(columnName, startValue, endValue);
        }
        return (T) this;
    }

    /**
     * 添加between条件
     * <pre>
     * {@literal
     * Object[] arr = new Object[]{1, 100};
     * query.orBetween(arr);
     * }
     * </pre>
     *
     * @param values 存放起始值、结束值，只能存放2个值，values[0]表示开始值，value[1]表示结束值
     * @return 返回Query对象
     */
    default T orBetween(String columnName, Object[] values) {
        getCondition().orBetween(columnName, values);
        return (T) this;
    }

    /**
     * 添加between条件
     *
     * @param expression 表达式，当为true时添加条件
     * @param columnName 数据库字段名
     * @param values     存放起始值、结束值，只能存放2个值，values[0]表示开始值，value[1]表示结束值
     * @return 返回Query对象
     */
    default T orBetween(boolean expression, String columnName, Object[] values) {
        if (expression) {
            orBetween(columnName, values);
        }
        return (T) this;
    }

    /**
     * 添加between条件
     * <pre>
     * {@literal
     * query.orBetween(Arrays.asList(1, 100));
     * }
     * </pre>
     *
     * @param values 存放起始值、结束值，只能存放2个值
     * @return 返回Query对象
     */
    default T orBetween(String columnName, List<?> values) {
        getCondition().orBetween(columnName, values);
        return (T) this;
    }

    /**
     * 添加between条件
     *
     * @param expression 表达式，当为true时添加条件
     * @param columnName 数据库字段名
     * @param values     存放起始值、结束值，只能存放2个值
     * @return 返回Query对象
     */
    default T orBetween(boolean expression, String columnName, List<?> values) {
        if (expression) {
            orBetween(columnName, values);
        }
        return (T) this;
    }

    /**
     * 添加between条件
     * <pre>
     * {@literal
     * query.orBetween(new BetweenValue(1, 100));
     * }
     * </pre>
     *
     * @param betweenValue 起始值、结束值包装对象
     * @return 返回Query对象
     */
    default T orBetween(String columnName, BetweenValue betweenValue) {
        getCondition().orBetween(columnName, betweenValue);
        return (T) this;
    }

    /**
     * 添加between条件
     *
     * @param expression   表达式，当为true时添加条件
     * @param columnName   数据库字段名
     * @param betweenValue 存放起始值、结束值，只能存放2个值
     * @return 返回Query对象
     */
    default T orBetween(boolean expression, String columnName, BetweenValue betweenValue) {
        if (expression) {
            orBetween(columnName, betweenValue);
        }
        return (T) this;
    }

    /**
     * 添加自定义sql条件
     *
     * @param orSql 自定义sql
     * @return 返回Query对象
     */
    default T orSql(String orSql) {
        getCondition().orSql(orSql);
        return (T) this;
    }

    /**
     * 根据表达式添加自定义sql条件
     *
     * @param expression 表达式，当为true时添加条件
     * @param orSql      自定义sql
     * @return 返回Query对象
     */
    default T orSql(boolean expression, String orSql) {
        if (expression) {
            orSql(orSql);
        }
        return (T) this;
    }

    /**
     * 添加自定义sql条件
     *
     * @param sqlFormat SQL模板，参数值使用?代替，如：<code>username = ? and nickname orLike '%?%'</code>
     * @param args      参数
     * @return 返回Query对象
     */
    default T orSql(String sqlFormat, Object... args) {
        getCondition().orSql(sqlFormat, args);
        return (T) this;
    }

    /**
     * 根据表达式添加自定义sql条件
     *
     * @param expression 表达式，当为true时添加条件
     * @param sqlFormat  SQL模板，参数值使用?代替，如：<code>username = ? and nickname orLike '%?%'</code>
     * @param args       参数
     * @return 返回Query对象
     */
    default T orSql(boolean expression, String sqlFormat, Object... args) {
        if (expression) {
            orSql(sqlFormat, args);
        }
        return (T) this;
    }

    /**
     * 添加字段不为null的条件
     *
     * @param column 数据库字段名
     * @return 返回Query对象
     */
    default T orNotNull(String column) {
        return this.orSql(column + " IS NOT NULL");
    }

    /**
     * 根据表达式添加字段不为null的条件
     *
     * @param expression 表达式，当为true时添加条件
     * @param column     数据库字段名
     * @return 返回Query对象
     */
    default T orNotNull(boolean expression, String column) {
        if (expression) {
            orNotNull(column);
        }
        return (T) this;
    }

    /**
     * 添加字段是null的条件
     *
     * @param column 数据库字段名
     * @return 返回Query对象
     */
    default T orIsNull(String column) {
        return this.orSql(column + " IS NULL");
    }

    /**
     * 根据表达式添加字段是null的条件
     *
     * @param expression 表达式，当为true时添加条件
     * @param column     数据库字段名
     * @return 返回Query对象
     */
    default T orIsNull(boolean expression, String column) {
        if (expression) {
            orIsNull(column);
        }
        return (T) this;
    }

    /**
     * 添加不为空字符串条件
     *
     * @param column 数据库字段名
     * @return 返回Query对象
     */
    default T orNotEmpty(String column) {
        return this.orSql(column + " IS NOT NULL AND " + column + " <> '' ");
    }

    /**
     * 根据表达式添加不为空字符串条件
     *
     * @param expression 表达式，当为true时添加条件
     * @param column     数据库字段名
     * @return 返回Query对象
     */
    default T orNotEmpty(boolean expression, String column) {
        if (expression) {
            orNotEmpty(column);
        }
        return (T) this;
    }

    /**
     * 添加空字段条件，null或者空字符串
     *
     * @param column 数据库字段名
     * @return 返回Query对象
     */
    default T orIsEmpty(String column) {
        return this.orSql(column + " IS NULL OR " + column + " = '' ");
    }

    /**
     * 根据表达式添加空字段条件，null或者空字符串
     *
     * @param expression 表达式，当为true时添加条件
     * @param column     数据库字段名
     * @return 返回Query对象
     */
    default T orIsEmpty(boolean expression, String column) {
        if (expression) {
            orIsEmpty(column);
        }
        return (T) this;
    }


}
